package run.leven.notice.starter.util;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import run.leven.notice.starter.common.Constants;
import run.leven.notice.starter.model.EmailDetail;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author leven
 * @date 2020/3/17 0:09
 */
@Slf4j
public class NoticeUtils implements ApplicationContextAware {


    private final static String BLANK = "";
    private static String APPLICATION_NAME;
    private static ApplicationContext context;
    private static volatile RabbitTemplate rabbitTemplate;

    private static RabbitTemplate getRabbitTemplate() {
        if (rabbitTemplate == null) {
            synchronized (NoticeUtils.class) {
                if (rabbitTemplate == null) {
                    rabbitTemplate =  context.getBean(RabbitTemplate.class);
                }
            }
        }
        return rabbitTemplate;
    }



    /**
     * 发送邮件
     *
     * @param emailDetail 邮件内容
     * @return taskId
     */
    public static String sendEmail(EmailDetail emailDetail, Long expiration, TimeUnit timeUnit) {
        try {
            Assert.state(emailDetail != null, "邮件不能为空!");
            Assert.state(isNotBlank(emailDetail.getSubject()), "邮件主题不能为空!");
            Assert.state(isNotBlank(emailDetail.getContent()), "邮件内容不能为空!");
            Assert.state(!CollectionUtils.isEmpty(emailDetail.getToAddressList()), "邮件收件人不能为空!");
            String taskId = createTaskId();
            emailDetail.setNoticeTaskId(taskId);
            MessageProperties messageProperties = new MessageProperties();
            long exp = timeUnit.toMillis(expiration);
            messageProperties.setExpiration(Long.toString(exp));
            ObjectMapper objectMapper = new ObjectMapper();
            byte[] body = objectMapper.writeValueAsBytes(JSONObject.toJSON(emailDetail).toString());
            Message message = new Message(body, messageProperties);
            getRabbitTemplate().convertAndSend(Constants.NOTICE_EXCHANGE, Constants.EMAIL_NOTICE, message);

            log.info("发送邮件到MQ成功，主题：{}，收件人：{}，内容：{},taskId:{}", emailDetail.getSubject(), emailDetail.getToAddressList(), emailDetail.getContent(), taskId);
            return taskId;
        } catch (AmqpException e) {
            log.error("发送邮件到MQ失败，失败原因", e);
        } catch (Exception e) {
            log.warn("发送邮件到MQ失败，失败原因:{}", e.getMessage());
        }
        return "";
    }

    private static boolean isNotBlank(String param) {
        return param != null && !BLANK.equals(param);
    }

    /**
     * 用于生成task id(共21位数字，可扩展)
     *
     * @return task id
     */
    private static String createTaskId() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String timeStr = sdf.format(new Date());
        int random = (int) (Math.random() * 9000 + 1000);
        return APPLICATION_NAME + "-" + timeStr + random;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
        String applicationName = context.getEnvironment().getProperty("spring.application.name");
        if (!isNotBlank(applicationName)){
            APPLICATION_NAME = applicationName;
        }else{
            APPLICATION_NAME = "DEFAULT";
        }
        log.info("NoticeUtil注入容器成功");
    }
}
